﻿using CRedis.Client;
using CRedis.Client.Entities;
using CRedis.Client.Logic;
using CRedis.Client.Pipeline;
using CRedis.Client.Utility;
using CRedis.Third.Redis;
using CRedis.Third.Redis.Pipeline;
using Newtonsoft.Json;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RedisClientTest
{
    //public class MyCachePipeline : CachePipeline
    //{
    //    private RedisCluster _redisCluster;
    //    private long _maxcount;
    //    private long enqueCount;
    //    public MyCachePipeline(RedisCluster cluster)
    //        : base(cluster)
    //    {
    //        if (ConfigurationManager.AppSettings["PipelineMaxCount"] != null)
    //        {
    //            this._maxcount = long.Parse(ConfigurationManager.AppSettings["PipelineMaxCount"]);
    //        }
    //    }
    //    public void Pop(string key, System.Action<string> onSuccessCallback)
    //    {
    //        this.PipelineAction(delegate(IRedisPipeline server)
    //        {
    //            server.QueueCommand((IRedisClient r) => { return r.PopItemFromList(key); }, onSuccessCallback);
    //        }, key);
    //    }
    //    public void Push(string key, string value)
    //    {
    //        this.PipelineAction(delegate(IRedisPipeline server)
    //        {
    //            server.QueueCommand((IRedisClient r) => r.PushItemToList(key, value));
    //        }, key);
    //    }
    //    private void PipelineAction(System.Action<IRedisPipeline> func, string key)
    //    {
    //        if (this._maxcount == 0L || this.enqueCount < this._maxcount)
    //        {
    //            RedisServer server = null;
    //            try
    //            {
    //                System.Collections.Generic.List<RedisServer> servers = this._redisCluster.GetGroupByKey(key).Masters;
    //                foreach (RedisServer srv in servers)
    //                {
    //                    server = srv;
    //                    IRedisPipeline pipelineServer = srv.GetPipelineClient();
    //                    func(pipelineServer);
    //                }
    //                this.enqueCount += 1L;
    //            }
    //            catch (System.Exception ex)
    //            {
    //                this.WriteError("PipelineSetError", ex, server.Cluster.Name, server);
    //                throw;
    //            }
    //        }
    //    }
    //    private void WriteError(string title, System.Exception ex, string clusterName, RedisServer server)
    //    {
    //        try
    //        {
    //            System.Collections.Generic.Dictionary<string, string> tags = new System.Collections.Generic.Dictionary<string, string>();
    //            tags.Add("clustername", clusterName);
    //            if (server != null)
    //            {
    //                tags.Add("serverip", server.IPAddress);
    //                tags.Add("serverport", server.Port.ToString());
    //                tags.Add("dbnumber", server.DBNumber.ToString());
    //            }
    //            RedisLogger.Error(title, ex, tags);
    //        }
    //        catch
    //        {
    //        }
    //    }
    //}
    class Program
    {
        static void Main(string[] args)
        {
            //ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
            //IDatabase db = redis.GetDatabase();

            //    Task[] tasks = new Task[10000];
            //for (int i = 0; i < 10000; i++)
            //{
            //   List<RedisValue> valueList = new List<RedisValue>();
            //    for (int j = 0; j < 500; j++)
            //    {
            //        valueList.Add(j.ToString());
            //    }
            //    tasks[i] = db.SetAddAsync("QuerySet" + i, valueList.ToArray());
            //    Console.WriteLine("QuerySet" + i + " done");
            //}
            //Task.WhenAll(tasks).Wait();

            //RedisCluster cluster = ClusterFactory.Create().GetCluster("MyTest");
            //MyCachePipeline pipeLine = new MyCachePipeline(cluster);
            //for (int i = 0; i < 100; i++)
            //{
            //    pipeLine.Push("PipeList", i.ToString());
            //}
            //pipeLine.Flush();
            //for (int i = 0; i < 100; i++)
            //{
            //    pipeLine.Pop("PipeList", r =>
            //        Console.WriteLine(string.Format("got {0} in thread :", r, Thread.CurrentThread.ManagedThreadId))
            //        );
            //}
            //pipeLine.Flush();
            //MyRedisCacheProvider provider = new MyRedisCacheProvider("frtproductservice");
            
            ICacheProvider provider = CacheFactory.GetPorvider("frtproductservice");// ("MyTest");
            provider.AddItemToSet("testSet", "item1");
            provider.AddItemToSet("testSet", "item1");
            string item = provider.PopItemFromSet("testSet");
            item = provider.PopItemFromSet("testSet");
            bool result = provider.Del("testSet");
            //provider.Remove("PipeList");
            //ICacheProvider provider = CacheFactory.GetPorvider("MyTest");            
            //Stopwatch sw = new Stopwatch();
            //sw.Start();
            //for (int i = 0; i < 1000; i++)
            //{
            //    provider.Set("key"+i, "value"+i); 
            //}
            //sw.Stop();
            //Console.WriteLine(sw.ElapsedMilliseconds);
            //sw.Restart();
            //RedisAllPurposePipeline pipeLine =new RedisAllPurposePipeline()
            //for (int i = 0; i < 1000; i++)
            //{

            //}
            //sw.Stop();
            //Console.WriteLine(sw.ElapsedMilliseconds);
            //string value = provider.Get<string>("key1");
            //provider.Remove("key1");

            //TaskCreator.Run();

            Console.WriteLine("press any key to exit");
            Console.ReadLine();
        }

        private static void HashTest()
        {
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect("localhost");
            IDatabase db = redis.GetDatabase();
            Stopwatch sw = new Stopwatch();

            string hashKey = "hash:entities";
            for (int j = 0; j < 1000; j++)
            {
                List<HashEntry> entryList = new List<HashEntry>();
                for (int i = 0; i < 500; i++)
                {
                    entryList.Add(new HashEntry("Field1:" + i, "Value1:" + i));
                    entryList.Add(new HashEntry("Field2:" + i, "Value2:" + i));
                    //db.HashSet(hashKey, "Field1:"+i, "Value1:" + i);
                    //db.HashSet(hashKey, "Field2:"+i, "Value2:" + i);
                }
                sw.Start();
                db.HashSet(hashKey + ":" + j, entryList.ToArray());
                sw.Stop();
            }
            Console.WriteLine("hash takes: " + sw.ElapsedMilliseconds + "ms");

            Console.WriteLine("press any key to continue...");
            Console.ReadLine();

            //hashKey = "hash:entity:";
            //for (int i = 0; i < 500; i++)
            //{
            //    db.HashSet(hashKey+i, "Field1:" + i, "Value1:" + i);
            //    db.HashSet(hashKey + i, "Field2:" + i, "Value2:" + i);
            //}

            //Console.WriteLine("press any key to continue...");
            //Console.ReadLine();

            //for (int j = 0; j < 500; j++)
            //{
            //    //StringBuilder valStrBuilder = new StringBuilder();
            //    string strKey = "string:Entity:" + j;
            //    Entity entity = new Entity { Field1 = "Value1:" + j, Field2 = "Value2:" + j };
            //    db.StringSet(strKey, JsonConvert.SerializeObject(entity));
            //    //string value = 
            //    //db.StringSet(strKey, valStrBuilder.ToString());
            //}
            //Console.WriteLine("press any key to continue...");
            //Console.ReadLine();
            sw.Reset();
            for (int i = 0; i < 1000; i++)
            {
                for (int j = 0; j < 500; j++)
                {
                    //StringBuilder valStrBuilder = new StringBuilder();
                    string strKey = "str:Entity:" + j * (i + 1);
                    sw.Start();
                    db.StringSet(strKey, "Value1:" + j * (i + 1) + "," + "Value2:" + j * (i + 1));
                    sw.Stop();
                    //string value = 
                    //db.StringSet(strKey, valStrBuilder.ToString());
                }
            }
            Console.WriteLine("string takes: " + sw.ElapsedMilliseconds + "ms");
            Console.WriteLine("done");
        }
    }

    public class Entity
    {
        public string Field1 { get; set; }
        public string Field2 { get; set; }
    }


}
